#include "IndexBuffer.h"
#include "ShaderProgram.h"
#include "Texture2D.h"
#include "VertexArray.h"
#include "VertexBuffer.h"
#include "GlfwWindow.h"
#include "VertexBufferLayout.h"
#include "glm/ext/matrix_clip_space.hpp"
#include "glm/ext/matrix_transform.hpp"
#include "glm/fwd.hpp"
#include "glm/trigonometric.hpp"

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    GlfwWindowManager window(1200, 900);
    if (!window.initWindow("LearnOpenGL")) {
        std::cout << "Failed to create GLFW window" << std::endl;
    }

    // 四组顶点
    float vertices[] = {0.5f,  0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 1.0, 1.0, 0.5f,  -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0, 0.0,
                        -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0, 0.0, -0.5f, 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0, 1.0};

    // 注意索引从0开始!
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标，
    // 这样可以由下标代表顶点组合成矩形
    unsigned int indices[] = {0, 1, 3, 1, 2, 3};

    VertexArray        vao;
    VertexBuffer       vbo(vertices, sizeof(vertices));
    VertexBufferLayout layout(8 * sizeof(float));
    layout.addAttribute(0, 3, GL_FLOAT, 0);
    layout.addAttribute(1, 3, GL_FLOAT, 3 * sizeof(float));
    layout.addAttribute(2, 2, GL_FLOAT, 6 * sizeof(float));
    vao.addBuffer(vbo, layout);

    IndexBuffer ibo(indices, 6);
    Texture2D   texture1("./textures/container.jpg");
    Texture2D   texture2("./textures/awesomeface.png");
    texture1.bind(0);
    texture2.bind(1);

    ShaderProgram shaderProgram("./shaders/example_basic/vertex.shader", "./shaders/example_basic/fragment.shader");
    shaderProgram.bind();

    // 设置每个采样器的方式告诉OpenGL每个着色器采样器属于哪个纹理单元
    shaderProgram.setUniform1i("u_texture1", 0);
    shaderProgram.setUniform1i("u_texture2", 1);

    glm::mat4 proj  = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
    glm::mat4 view  = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f));
    glm::mat4 model = glm::rotate(glm::mat4(1.0f), glm::radians(1.0f), glm::vec3(1.0f, 0.0f, 0.0f));

    shaderProgram.setUniformMat4fv("u_proj", proj);
    shaderProgram.setUniformMat4fv("u_view", view);
    shaderProgram.setUniformMat4fv("u_model", model);

    // 使用线框模式绘制
    // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // 启用深度测试
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.2f, 0.2f, 0.3f, 1.0f);
    window.loopRender([&]() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    });
    return 0;
}